#include <iostream>
#include <string>
#include <vector>
#include <cstring>
#include <pthread.h>
#include <unistd.h>

using namespace std;

#include "LockGuard.hpp"

#define NUM 5

pthread_mutex_t lock;

struct ThreadData
{
    ThreadData(int number)
    {
        threadname = "thread-" + to_string(number);
    }

    string threadname;
};

int tickets = 1000;

void* GetTicket(void* args)
{
    // ThreadData* td = (ThreadData*)args;
    ThreadData* td = static_cast<ThreadData*>(args);
    const char* name = td->threadname.c_str();
    while (true)
    {
        { // 限定锁的作用域
            // pthread_mutex_lock(&lock);
            LockGuard lockguard(&lock);
            if (tickets > 0)
            {
                usleep(1000);
                printf("%s get a ticket: %d\n", name, tickets);
                tickets--;
                pthread_mutex_unlock(&lock);
            }
            else
            {
                pthread_mutex_unlock(&lock);
                break;
            }
        }

        usleep(50); // 模拟抢到票之后的后续动作，防止持有锁的进程竞争力过强
    }

    printf("%s quit\n", name);
}

int main()
{
    pthread_mutex_init(&lock, nullptr); 

    vector<pthread_t> tids; // 用做下面creat的输出型参数
    vector<ThreadData*> thread_datas;
    for (int i = 1; i <= NUM; i++)
    {
        pthread_t tid;
        ThreadData* td = new ThreadData(i);
        thread_datas.push_back(td);
        // 使用线程库时记得链接！！！
        pthread_create(&tid, nullptr, GetTicket, thread_datas[i - 1]);
        tids.push_back(tid);
    }

    // 线程等待
    for (auto td : tids)
    {
        pthread_join(td, nullptr);
    }

    // 释放空间
    for (auto td : thread_datas)
    {
        delete td;
    }

    pthread_mutex_destroy(&lock);

    return 0;
}